using Godot;

public partial class PlayerController : CharacterBody3D
{
	[ExportSubgroup("Components")]
	[Export] private Node3D view;
	[Export] private MeshInstance3D model;

	[ExportSubgroup("Properties")]
	[Export] private float movementSpeed = 200f;
	[Export] private float jumpStrength = 10f;

	Vector3 movementVelocity = Vector3.Zero;
	private float rotationDirection = 0f;
	private float gravity = 0f;

	private bool previously_floored = false;

	private bool jumpSingle = true;
	private bool jumpDouble = true;
	private Vector3 input = Vector3.Zero;
	private Vector3 appliedVelocity = Vector3.Zero;

	public override void _PhysicsProcess(double delta)
	{
		//Handle functions
		HandleControls(delta);
		HandleGravity(delta);

		//HandleAnimations();

		//Movement
		appliedVelocity = Velocity.Lerp(movementVelocity, (float)delta * 10);
		appliedVelocity.Y = -gravity;

		Velocity = appliedVelocity;
		MoveAndSlide();

		//Rotation
		if (Velocity.Length() > 0)
		{
			rotationDirection = new Vector2(Velocity.Z, Velocity.X).Angle();
			GD.Print("有转动");
		}
		
		if(input.Length() > 0)
		{
			model.Rotation = new Vector3(0, Mathf.LerpAngle(model.Rotation.Y, rotationDirection, (float)delta * 10), 0);
		}
		
		//Scale animation
		model.Scale = model.Scale.Lerp(new Vector3(1, 1, 1), (float)delta * 10);

		//Animation when landing
		if (IsOnFloor() && gravity > 2 && !previously_floored)
		{
			model.Scale = new Vector3(1.25f, 0.75f, 1.25f);
		}

		previously_floored = IsOnFloor();
	}

	private void HandleControls(double delta)
	{
		//Movement
		input.X = Input.GetAxis("LeftStick_Left", "LeftStick_Right");
		input.Z = Input.GetAxis("LeftStick_Up", "LeftStick_Down");

		input = input.Rotated(Vector3.Up, view.Rotation.Y).Normalized();

		movementVelocity = input * movementSpeed * (float)delta;

		//Jumping
		if (Input.IsActionJustPressed("Jump"))
		{
			if (jumpDouble)
			{
				gravity = -jumpStrength;
				jumpDouble = false;
				model.Scale = new Vector3(0.5f, 1.5f, 0.5f);
			}

			if (jumpSingle)
			{
				Jump();
			}
		}
	}

	private void HandleGravity(double delta)
	{
		gravity += 25f * (float)delta;

		if (gravity > 0f && IsOnFloor())
		{
			jumpSingle = true;
			gravity = 0f;
		}
	}

	private void Jump()
	{
		gravity = -jumpStrength;

		model.Scale = new Vector3(0.5f, 1.5f, 0.5f);

		jumpSingle = false;
		jumpDouble = true;
	}

	// private void HandleAnimations(){}
}
